//电子邮件puhalskijsemen@gmail.com
//源码网站 开vpn全局模式打开 http://web3incubators.com/
//电报https://t.me/gamecode999
//网页客服 http://web3incubators.com/kefu.html
import CommonUtils from "./CommonUtils";
import { EVENT_TYPE } from "./EvenType";
import { EventMgrInstance } from "./EventManager";
import { Excel } from "./Excel";
import { ExcelUtil } from "./ExcelUtil";
import { GameDataMgr } from "./GameDataManager";
import { GameGlobalVariable } from "./GameGlobalVariable";
import FruitDataManager from "./HallGlobalVariable";
import { PlayerDataMgr } from "./PlayerDataManager";
import { SingletonBase } from "./SingletonManager";
import ViewMosterLogic from "./UI_MosterLogic";
import ViewPlayer from "./UI_Player";

class BuffManager extends SingletonBase {
    public ciTiaoData: any[] = [];
    public offTime: number = 0;
    public monsterBombCount: { [key: string]: number } = {};
    public attackCount: { [key: string]: { [key: string]: number } } = {};
    public currentWaveCount: number = 0;
    public monsterBomb: { [key: string]: string } = {};
    public durianCountRecord: { [key: string]: number } = {};
    public intervalCount: { [key: string]: number } = {};
    public playerSendCount: { [key: string]: number } = {};

    /**
     * 添加当前词条
     * @param entry 词条数据
     * 建议方法名：addCurrentCiTiao
     */
    public addCurrentCiTiao(entry: any): void {
        if (!this.addSingleCiTiao(entry)) {
            this.ciTiaoData.push(entry);
        }
    }

    /**
     * 保存当前词条
     * 建议方法名：saveCurrentCiTiao
     */
    public saveCurrentCiTiao(): void {
        GameDataMgr.updateCiTiaoData(GameGlobalVariable.nowlevel, this.ciTiaoData);
    }

    /**
     * 结束奖励
     * @param reward 奖励值
     * @returns 最终奖励值
     * 建议方法名：calculateFinalAward
     */
    public calculateFinalAward(reward: number): number {
        let totalBonus = 0;
        for (const ciTiao of this.ciTiaoData) {
            const buff = Excel.shuiguobuff(ciTiao.citiaoshuzhitype);
            if (buff.buffefftype === 6) {
                totalBonus += buff.value[0];
            }
        }
        return reward + totalBonus;
    }

    /**
     * 添加单个词条
     * @param entry 词条数据
     * @returns 是否成功添加
     * 建议方法名：addSingleCiTiao
     */
    public addSingleCiTiao(entry: any): boolean {
        const buff = Excel.shuiguobuff(entry.citiaoshuzhitype);
        let isAdded = false;
        if (buff.buffefftype === 44) {
            EventMgrInstance.emitEvent(EVENT_TYPE.Game_Add_YinBi, buff.value[0]);
            isAdded = true;
        }
        return isAdded;
    }

    /**
     * 设置保存的词条
     * @param entries 词条数据数组
     * 建议方法名：setSavedCiTiao
     */
    public setSavedCiTiao(entries: any[]): void {
        this.ciTiaoData = entries;
    }

    /**
     * 获取玩家词条
     * @param player 玩家数据
     * @returns 玩家词条数组
     * 建议方法名：getPlayerCiTiaoList
     */
    public getPlayerCiTiaoList(player: any): any[] {
        return this.ciTiaoData.filter(ciTiao => {
            return ciTiao.citiaochuxian === 1 || ciTiao.shuiguoId === player.playerId + 1000;
        });
    }

    /**
     * 清除当前词条
     * 建议方法名：clearCurrentCiTiao
     */
    public clearCurrentCiTiao(): void {
        this.ciTiaoData = [];
        GameDataMgr.updateCiTiaoData(GameGlobalVariable.nowlevel, null);
        EventMgrInstance.emitEvent(EVENT_TYPE.Game_Add_CiTiao);
    }

    /**
     * 获取当前词条
     * @param isRandom 是否随机
     * @returns 当前词条数组
     * 建议方法名：getCurrentCiTiao
     */
    public getCurrentCiTiao(isRandom: boolean): any[] {
        const allCiTiao = Excel.shuiguocitiao_all;
        const availableCiTiao = [];
        const ciTiaoSize = allCiTiao.size;

        const addCiTiao = (index: number) => {
            const ciTiao = Excel.shuiguocitiao(index);
            if (ciTiao.citiaoshuzhitype !== 0 && ![59, 60, 64].includes(ciTiao.id)) {
                let ciTiaoIndex = -1;
                if (ciTiao.citiaochuxian === -1) {
                    ciTiaoIndex = this.ciTiaoData.findIndex((item) => item.id === ciTiao.id);
                }
                if (ciTiaoIndex === -1 && 
                    (ciTiao.citiaochuxian !== -1 || (PlayerDataMgr.getEquipIsDressUp(ciTiao.shuiguoId) && FruitDataManager.getUnLockCiTiao(ciTiao)))) {
                    availableCiTiao.push({ index: index - 1, weight: ciTiao.weigth });
                }
            }
        };

        for (let i = 1; i <= ciTiaoSize; i++) {
            addCiTiao(i);
        }

        if (isRandom) {
            return this.selectRandomCiTiao(availableCiTiao);
        }

        return this.selectHighQualityCiTiao(availableCiTiao);
    }

    private selectRandomCiTiao(availableCiTiao: { index: number, weight: number }[]): any[] {
        const selectedCiTiao = [];
        for (let i = 0; i < 3; i++) {
            const randomIndex = this.randomWeightIndex(availableCiTiao);
            selectedCiTiao.push(Excel.shuiguocitiao(availableCiTiao[randomIndex].index + 1));
            availableCiTiao.splice(randomIndex, 1);
        }
        return selectedCiTiao;
    }

    private selectHighQualityCiTiao(availableCiTiao: { index: number, weight: number }[]): any[] {
        const highQualityCiTiao = [];
        const mediumQualityCiTiao = [];

        for (let i = 0; i < availableCiTiao.length; i++) {
            const ciTiaoIndex = availableCiTiao[i].index;
            const ciTiao = Excel.shuiguocitiao(ciTiaoIndex + 1);
            if (ciTiao.quality === 3 && highQualityCiTiao.length < 2) {
                highQualityCiTiao.push(i);
            }
            if (ciTiao.quality === 2 && mediumQualityCiTiao.length < 1) {
                mediumQualityCiTiao.push(i);
            }
        }

        const selectedCiTiao = highQualityCiTiao.concat(mediumQualityCiTiao);
        return selectedCiTiao.map(index => Excel.shuiguocitiao(availableCiTiao[index].index + 1));
    }

    /**
     * 随机权重
     * @param weightArray 权重数组
     * @returns 随机索引
     * 建议方法名：randomWeightIndex
     */
    public randomWeightIndex(weightArray: { weight: number }[]): number {
        let totalWeight = weightArray.reduce((sum, item) => sum + item.weight, 0);
        let randomWeight = totalWeight * Math.random();
        for (let i = 0; i < weightArray.length; i++) {
            randomWeight -= weightArray[i].weight;
            if (randomWeight <= 0) {
                return i;
            }
        }
        return 0;
    }

    /**
     * 怪物被击中
     * @param monster 攻击对象
     * @param player 玩家对象
     * 建议方法名：monsterHit
     */
    public monsterHit(monster: ViewMosterLogic, player: any): void {
        let bestBuff = null;
        for (const ciTiao of this.ciTiaoData) {
            const buff = Excel.shuiguobuff(ciTiao.citiaoshuzhitype);
            if (ciTiao.shuiguoId === player.playerId + 1000) {
                if (buff.buffefftype === 1) {
                    if (!bestBuff || bestBuff.bufftime < buff.bufftime) {
                        bestBuff = buff;
                    }
                } else {
                    monster.applySpeedReduction(buff, player);
                }
            }
            if (buff.buffefftype === 24 && player.kuangrePlayer) {
                monster.applySpeedReduction(buff, player);
            }
        }
        this.applyPlayerBuff(monster, player, bestBuff);
    }

    private applyPlayerBuff(monster: ViewMosterLogic, player: any, bestBuff: any) {
        const playerBuff = Excel.shuiguobuff(player.sgtianfuid);
        if (playerBuff) {
            monster.applySpeedReduction(playerBuff, player);
        }
        if (bestBuff) {
            monster.applySpeedReduction(bestBuff, player);
        }
        const equipData = ExcelUtil.getMatchingData(Excel.shuiguohecheng_all, "shuiguoId", player.playerId + 1000)[player.playerInfo.equipLevel];
        if (equipData) {
            const newBuff = Excel.shuiguobuff(equipData.newTianFuBuff);
            if (newBuff) {
                monster.applySpeedReduction(newBuff, player);
            }
        }
    }

    /**
     * 获取毒雾buff
     * @returns 毒雾buff
     * 建议方法名：getPoisonFog
     */
    public getPoisonFog(): any {
        return this.findBuffByEffectType(37);
    }

    /**
     * 获取毒伤buff
     * @returns 毒伤buff
     * 建议方法名：getPoisonDamage
     */
    public getPoisonDamage(): any {
        return this.findBuffByEffectType(41);
    }

    private findBuffByEffectType(effectType: number): any {
        // for (const ciTiao of this.ciTiaoData) { 
        //     dsafasdfurt
        //     const buff = Excel.shuiguobuff(ciTiao.citiaoshuzhitype);
        //     if (buff.buffefftype === effectType) {
        //         return buff;
        //     }
        // }
        // return null;


        let poisonDamage = null;
        for (let i = 0; i < this.ciTiaoData.length; i++) {
            const ciTiao = this.ciTiaoData[i];
            const buff = Excel.shuiguobuff(ciTiao.citiaoshuzhitype);
            if (buff.buffefftype === effectType) {
                poisonDamage = buff;
            }
        }
        return poisonDamage;
    }

    /**
     * 增加怪物炸弹计数
     * @param monsterNode 怪物节点
     * 建议方法名：incrementMonsterBombCount
     */
    public addMosterBombCount(monsterNode: any): void {
        const nodeId = monsterNode.node.uuid;
        this.monsterBombCount[nodeId] = (this.monsterBombCount[nodeId] || 0) + 1;
    }

    /**
     * 清除怪物炸弹计数
     * @param monsterNode 怪物节点
     * 建议方法名：clearMonsterBombCount
     */
    public clearMonsterBombCount(monsterNode: any): void {
        delete this.monsterBombCount[monsterNode.node.uuid];
    }

    /**
     * 获取怪物炸弹航海计数
     * @param monsterNode 怪物节点
     * @returns 航海计数
     * 建议方法名：getMonsterBombSailingCount
     */
    public getMonsterBombSailingCount(monsterNode: any): number {
        const nodeId = monsterNode.node.uuid;
        if (this.hasBuffEffectType(31)) {
            const bombCount = this.monsterBombCount[nodeId] || 0;
            return 0.1 * bombCount;
        }
        return 0;
    }

    /**
     * 获取怪物炸弹增伤
     * @returns 增伤值
     * 建议方法名：getMonsterBombDamageIncrease
     */
    public getMonsterBombDamageIncrease(): number {
        return this.calculateBuffValueByEffectType(29, 100);
    }

    /**
     * 获取二级水果buff
     * @returns 二级水果buff
     * 建议方法名：getSecondaryFruitBuff
     */
    public getSecondaryFruitBuff(): any {
        return this.findBuffByEffectType(45);
    }

    /**
     * 增加玩家攻击
     * @param attackTarget 攻击对象
     * @param player 玩家对象
     * @returns 增加的攻击值
     * 建议方法名：incrementPlayerAttack
     */
    public addPlayerAttack(attackTarget: any, player: any): number {
        let buff = Excel.shuiguobuff(player.sgtianfuid);
        if (!buff || buff.buffefftype !== 16) {
            buff = this.getNewTianFuBuff(player);
        }
        if (buff && buff.buffefftype === 16) {
            return this.calculateAttackIncrease(attackTarget, player, buff);
        }
        return 0;
    }

    private getNewTianFuBuff(player: any): any {
        const equipData = ExcelUtil.getMatchingData(Excel.shuiguohecheng_all, "shuiguoId", player.playerId + 1000)[player.playerInfo.equipLevel];
        if (equipData) {
            return Excel.shuiguobuff(equipData.newTianFuBuff);
        }
        return null;
    }

    private calculateAttackIncrease(attackTarget: any, player: any, buff: any): number {
        const attackNodeId = attackTarget.node.uuid;
        const playerNodeId = player.node.uuid;
        let attackCount = (this.attackCount[attackNodeId] && this.attackCount[attackNodeId][playerNodeId]) || 0;
        attackCount = Math.min(attackCount + 1, buff.value[1]);
        if (!this.attackCount[attackNodeId]) {
            this.attackCount[attackNodeId] = {};
        }
        this.attackCount[attackNodeId][playerNodeId] = attackCount;
        return (buff.value[0] / 100) * attackCount;
    }

    /**
     * 清除怪物叠加
     * @param monsterNode 怪物节点
     * 建议方法名：clearMonsterStack
     */
    public clearMonsterStack(monsterNode: any): void {
        delete this.attackCount[monsterNode.node.uuid];
    }

    /**
     * 波数攻击增加
     * 建议方法名：incrementWaveAttack
     */
    public boshuAttackAdd(): void {
        this.currentWaveCount += this.countBuffEffectType(48);
    }

    /**
     * 获取攻击增加
     * @returns 攻击增加值
     * 建议方法名：getAttackIncrease
     */
    public getAttackIncrease(): number {
        const buff = this.findBuffByEffectType(48);
        if (buff) {
            let attackIncrease = buff.value[0] * this.currentWaveCount;
            if (attackIncrease > buff.value[1]) {
                attackIncrease = buff.value[1];
            }
            return attackIncrease / 100;
        }
        return 0;
    }

    /**
     * 重置当前波数
     * 建议方法名：resetCurrentWave
     */
    public resetCurrentWave(): void {
        this.currentWaveCount = 0;
    }

    /**
     * 玩家攻击方式进行中
     * @param player 玩家对象
     * @param attackMode 攻击方式
     * @returns 最终攻击方式
     * 建议方法名：playerAttackModeInProgress
     */
    public playerAttackModeInProgress(player: any, attackMode: number): number {
        const buff = this.findPlayerBuffByEffectType(player, 14);
        return buff ? 2 : attackMode;
    }

    /**
     * 播放攻击加成
     * @param player 玩家对象
     * @param attackValue 攻击值
     * @param attackType 攻击类型
     * @returns 最终攻击值
     * 建议方法名：applyAttackBonus
     */
    public applyAttackBonus(player: any, attackValue: number, attackType: number): number {
        let attackBonus = 0;
        for (const ciTiao of this.ciTiaoData) {
            const buff = Excel.shuiguobuff(ciTiao.citiaoshuzhitype);
            if (ciTiao.shuiguoId === player.playerId + 1000 || ciTiao.citiaochuxian === 1) {
                attackBonus += this.calculateAttackBonus(buff, player, attackType);
            }
        }
        if (player.kuangrePlayer) {
            attackBonus += this.calculateFrenzyAttackBonus(player);
        }
        return this.applyAttackTypeBonus(attackValue, attackBonus, attackType);
    }

    private calculateAttackBonus(buff: any, player: any, attackType: number): number {
        let bonus = 0;
        if (attackType === 1 && [15, 38].includes(buff.buffefftype)) {
            bonus += buff.value[0] / 100;
        } else if (attackType === 2) {
            if (buff.buffefftype === 17) {
                bonus += Math.min(buff.value[0] / 100, 3);
            } else if (buff.buffefftype === 33) {
                bonus += this.calculateSendCountBonus(player, buff);
            }
        }
        if (attackType === 2 && buff.buffefftype === 28 && player.playerId !== 3) {
            bonus += (buff.value[0] / 100) * this.getBeOhterShuiGuoBuff(player);
        }
        if (attackType === 1 && buff.buffefftype === 9 && player.playerId !== 3) {
            bonus += (buff.value[0] / 100) * this.getBeOhterShuiGuoBuff(player);
        }
        return bonus;
    }

    private calculateSendCountBonus(player: any, buff: any): number {
        const playerNodeId = player.node.uuid;
        let sendCount = this.playerSendCount[playerNodeId] || 1;
        sendCount = Math.min(sendCount, 15);
        return (buff.value[0] / 100) * sendCount;
    }

    private calculateFrenzyAttackBonus(player: any): number {
        return this.addTalent(player).reduce((bonus, tianFuBuff) => {
            return bonus + (tianFuBuff.buffefftype === 40 ? tianFuBuff.value[0] / 100 : 0);
        }, 0);
    }

    private applyAttackTypeBonus(attackValue: number, attackBonus: number, attackType: number): number {
        const attackAdd = this.getAttackIncrease();
        if (attackType === 1) {
            return attackValue * (1 + attackBonus + attackAdd);
        } else if (attackType === 2) {
            return attackValue / (1 + attackBonus);
        }
        return attackValue;
    }

    /**
     * 获取怪物所有伤害
     * @param baseDamage 初始伤害值
     * @returns 最终伤害值
     * 建议方法名：getTotalMonsterDamage
     */
    public getTotalMonsterDamage(baseDamage: number): number {
        const totalBonus = this.ciTiaoData.reduce((sum, ciTiao) => {
            const buff = Excel.shuiguobuff(ciTiao.citiaoshuzhitype);
            return ciTiao.citiaochuxian === 1 && buff.buffefftype === 43 
                ? sum + buff.value[0] / 100 
                : sum;
        }, 0);
        return baseDamage * (1 + totalBonus);
    }

    /**
     * 获取怪物炸弹加成
     * @param monsterNode 怪物节点
     * @returns 加成值
     * 建议方法名：getMonsterBombBonus
     */
    public getMonsterBombBonus(monsterNode: any): number {
        if (this.monsterBomb[monsterNode.node.uuid]) {
            const bombBuff = this.findBuffByEffectType(31);
            return bombBuff ? bombBuff.value[0] / 100 : 0;
        }
        return 0;
    }

    /**
     * 获取流血加成
     * @param player 玩家对象
     * @returns 加成值
     * 建议方法名：getBleedBonus
     */
    public getBleedBonus(player: any): number {
        const bleedBuff = this.findPlayerBuffByEffectType(player, 49);
        return bleedBuff ? bleedBuff.value[0] / 100 : 0;
    }

    /**
     * 设置怪物炸弹
     * @param nodeId 怪物节点UUID
     * 建议方法名：setMonsterBomb
     */
    public setMonsterBomb(nodeId: string): void {
        this.monsterBomb[nodeId] = "ok";
    }

    /**
     * 清除怪物炸弹
     * @param nodeId 怪物节点UUID
     * 建议方法名：clearMonsterBomb
     */
    public cleanMosterBomb(nodeId: string): void {
        delete this.monsterBomb[nodeId];
    }

    /**
     * 获取炸弹buff范围
     * @param player 玩家对象
     * @returns 范围值
     * 建议方法名：getBombBuffScope
     */
    public getBombBuffScope(player: ViewPlayer): number {
        const rangeBuff = this.findPlayerBuffByEffectType(player, 4);
        return rangeBuff ? rangeBuff.value[0] / 100 : 0;
    }

    /**
     * 设置炸弹伤害
     * @param player 玩家对象
     * @param monster 怪物对象
     * 建议方法名：setBombDamage
     */
    public setBombDamage(player: ViewPlayer, monster: any): void {
        const bombBuff = this.findPlayerBuffByEffectType(player, 42);
        if (bombBuff) {
            EventMgrInstance.emitEvent(
                EVENT_TYPE.Game_Add_BaoZha,
                monster.node.getPosition(),
                2,
                bombBuff.value[0]
            );
            const monsterNodes = monster.getNowMosterNode(bombBuff.value[0]);
            let attackValue = this.applyAttackBonus(player, player.sgattack, 1);
            attackValue += (attackValue * bombBuff.value[1]) / 100;
            monsterNodes.forEach((monsterNode: any) => {
                monsterNode.getComponent(ViewMosterLogic).fujiaAttack(attackValue, 1, player);
            });
        }
    }

    /**
     * 获取范围buff
     * @param player 玩家对象
     * @returns 范围buff
     * 建议方法名：getRangeBuff
     */
    public getRangeBuff(player: any): any {
        return this.findPlayerBuffByEffectType(player, 36);
    }

    /**
     * 获取炸弹buff
     * @param player 玩家对象
     * @returns 炸弹buff
     * 建议方法名：getBombBuff
     */
    public getBombBuff(e: any): any {
        // return this.getBuffByEffectTypeOrNewTalentBuff(player, 4);


        var t = null;
        for (var o = 0; o < this.ciTiaoData.length; o++) {
            var n = this.ciTiaoData[o];
            if (
                n.shuiguoId == e.playerId + 1e3 &&
                4 == (i = Excel.shuiguobuff(n.citiaoshuzhitype)).buffefftype
            ) {
                t = i;
                break;
            }
        }
        if (!t) {
            var i;
            var a = ExcelUtil.getMatchingData(Excel.shuiguohecheng_all, "shuiguoId", e.playerId + 1e3)[
                e.playerInfo.equipLevel
            ];
            if (a && (i = Excel.shuiguobuff(a.newTianFuBuff)) && 4 == i.buffefftype) {
                t = i;
            }
        }
        return t;
    }

    private findPlayerBuffByEffectType(player: ViewPlayer, effectType: number): any {
        for (const ciTiao of this.ciTiaoData) {
            if (ciTiao.shuiguoId === player.playerId + 1000) {
                const buff = Excel.shuiguobuff(ciTiao.citiaoshuzhitype);
                if (buff.buffefftype === effectType) {
                    return buff;
                }
            }
        }
        return null;
    }

    /**
     * 获取蓝瓜额外buff
     * @param player 玩家对象
     * @returns 蓝瓜额外buff
     * 建议方法名：getBlueMelonExtraBuff
     */
    public getBlueMelonExtraBuff(player: ViewPlayer): any {
        return this.findPlayerBuffByEffectType(player, 32);
    }

    /**
     * 获取其他水果buff
     * @param e 玩家对象
     * @returns 其他水果buff数量
     * 建议方法名：getOtherFruitBuffCount
     */
    public getBeOhterShuiGuoBuff(e: any): number {
        const siblings = e.node.parent.children;
        let count = 0;
        for (let i = 0; i < siblings.length; i++) {
            const sibling = siblings[i];
            if (e.node.uuid !== sibling.uuid && sibling.getComponent(ViewPlayer).playerId === 3) {
                const dirChildren = sibling.getChildByName("dir").children;
                for (let j = 0; j < dirChildren.length; j++) {
                    const dirChild = dirChildren[j];
                    const x = dirChild.x + sibling.x;
                    const y = dirChild.y + sibling.y;
                    if (CommonUtils.isPointInRect(cc.v2(x, y), e.node)) {
                        count++;
                        break;
                    }
                }
            }
        }
        return count;
    }

    /**
     * 获取榴莲buff
     * @param player 玩家对象
     * @returns 榴莲buff
     * 建议方法名：getDurianBuff
     */
    public getDurianBuff(player: any): any {
        return this.getDurianCountBuff(player, 30, 3);
    }

    /**
     * 获取榴莲炸弹
     * @param player 玩家对象
     * @returns 榴莲炸弹buff
     * 建议方法名：getDurianBomb
     */
    public getDurianBomb(e: any): any {
        let durianBomb = null;
        const equipData = ExcelUtil.getMatchingData(Excel.shuiguohecheng_all, "shuiguoId", e.playerId + 1000)[e.playerInfo.equipLevel];
        if (equipData) {
            const newBuff = Excel.shuiguobuff(equipData.newTianFuBuff);
            if (newBuff.buffefftype === 49) {
                durianBomb = newBuff;
            }
        }
        return durianBomb;
    }

    private getDurianCountBuff(player: any, effectType: number, maxCount: number): any {
        const durianBuff = this.findPlayerBuffByEffectType(player, effectType);
        if (durianBuff) {
            const playerNodeId = player.node.uuid;
            let count = (this.durianCountRecord[playerNodeId] || 0) + 1;
            this.durianCountRecord[playerNodeId] = count;
            if (count > maxCount) {
                this.durianCountRecord[playerNodeId] = 0;
                return durianBuff;
            }
        }
        return null;
    }

    /**
     * 清除榴莲计数
     * 建议方法名：clearDurianCount
     */
    public cleanLiuLian(): void {
        this.durianCountRecord = {};
    }

    /**
     * 获取攻击暴击
     * @param player 玩家对象
     * @param reset 是否重置
     * @returns 暴击几率和暴击加成
     * 建议方法名：getAttackCritical
     */
    // public getAttackBaoJi(player: any, reset: boolean = false): { baojijilv: number, baojijiacheng: number } {
    public getAttackCritical(player: any, reset: boolean = false): { baojijilv: number, baojijiacheng: number } {
        let criticalChance = 0;
        let criticalBonus = 0;
        let intervalBuff = null;

        for (const ciTiao of this.ciTiaoData) {
            const buff = Excel.shuiguobuff(ciTiao.citiaoshuzhitype);
            if (player.kuangrePlayer && player.kuangrePlayer.playerId + 1000 === ciTiao.shuiguoId) {
                if (buff.buffefftype === 26) {
                    criticalChance += buff.value[0] / 100;
                }
                if (buff.buffefftype === 23) {
                    criticalBonus += buff.value[0] / 100;
                }
            }
            if (ciTiao.shuiguoId !== player.playerId + 1000 && ciTiao.shuiguoId) {
                continue;
            }
            if (buff.buffefftype === 12) {
                criticalChance += buff.value[0] / 100;
            }
            if (buff.buffefftype === 13) {
                criticalBonus += buff.value[0] / 100;
            }
            if (buff.buffefftype === 34) {
                intervalBuff = buff;
            }
        }

        criticalChance = this.applyIntervalBuff(player, intervalBuff, criticalChance, reset);

        return { baojijilv: criticalChance, baojijiacheng: criticalBonus };
    }

    private applyIntervalBuff(player: any, intervalBuff: any, criticalChance: number, reset: boolean): number {
        if (intervalBuff) {
            const playerNodeId = player.node.uuid;
            let intervalCount = this.intervalCount[playerNodeId] || 0;
            if (!reset) {
                intervalCount += 1;
            }
            this.intervalCount[playerNodeId] = intervalCount;
            if (intervalCount > intervalBuff.value[0]) {
                this.intervalCount[playerNodeId] = 0;
                criticalChance = 1;
            }
        }
        return criticalChance;
    }

    /**
     * 获取狂热结束
     * @returns 是否结束
     * 建议方法名：isFrenzyOver
     */
    // public getKuangReOver(): boolean {
    public isFrenzyOver(): boolean {
        return this.ciTiaoData.some(ciTiao => {
            return Excel.shuiguobuff(ciTiao.citiaoshuzhitype).buffefftype === 25;
        });
    }

    /**
     * 获取柠檬真实
     * @param player 玩家对象
     * @returns 柠檬真实对象数组
     * 建议方法名：getLemonReal
     */
    // public getNinMengReal(player: any): any[] {
    public getLemonReal(player: any): any[] {
        const siblings = player.node.parent.children;
        const lemonReal = [];
        for (let i = 0; i < siblings.length; i++) {
            const sibling = siblings[i];
            if (sibling.uuid !== player.node.uuid) {
                const playerComponent = sibling.getComponent(ViewPlayer);
                if (playerComponent.playerId === 3) {
                    const dirChildren = sibling.getChildByName("dir").children;
                    for (let j = 0; j < dirChildren.length; j++) {
                        const dirChild = dirChildren[j];
                        const x = dirChild.x + sibling.x;
                        const y = dirChild.y + sibling.y;
                        if (CommonUtils.isPointInRect(cc.v2(x, y), player.node)) {
                            lemonReal.push(playerComponent);
                            break;
                        }
                    }
                }
            }
        }
        return lemonReal;
    }

    /**
     * 获取固定攻击
     * @param player 玩家对象
     * @returns 固定攻击值
     * 建议方法名：getFixedAttack
     */
    // public getAttackGuding(player: any): number {
    public getFixedAttack(player: any): number {
        const otherBuffCount = this.getBeOhterShuiGuoBuff(player);
        const fixedAttack = this.ciTiaoData.reduce((sum, ciTiao) => {
            const buff = Excel.shuiguobuff(ciTiao.citiaoshuzhitype);
            return buff.buffefftype === 21 ? sum + buff.value[0] * otherBuffCount : sum;
        }, 0);

        const lemonReal = this.getLemonReal(player);
        return lemonReal.reduce((sum, lemonPlayer) => {
            const lemonData = Excel.shuiguo(lemonPlayer.playerId + 1000);
            const lemonBuff = Excel.shuiguobuff(lemonData.talent);
            return sum + this.getLemonResult(lemonPlayer, lemonBuff);
        }, fixedAttack);
    }

    /**
     * 获取柠檬结果
     * @param lemonPlayer 玩家对象
     * @param buff buff对象
     * @returns 结果值
     * 建议方法名：getLemonResult
     */
    // public getNinMengRes(lemonPlayer: any, buff: any): number {
    public getLemonResult(lemonPlayer: any, buff: any): number {
        const levelData = ExcelUtil.getMatchingData(Excel.shuiguolevel_all, "shuiguoId", lemonPlayer.playerId + 1000);
        const equipLevel = PlayerDataMgr.getEquipDataById(lemonPlayer.playerId + 1000).level;
        
        const additionalValue = levelData.slice(0, equipLevel).reduce((sum, data, index) => {
            return index > 0 ? sum + data.addbeidongbuff[0] : sum;
        }, 0);

        const equipData = ExcelUtil.getMatchingData(Excel.shuiguohecheng_all, "shuiguoId", lemonPlayer.playerId + 1000)[lemonPlayer.playerInfo.equipLevel];
        const equipBonus = equipData ? equipData.addbeidongbuff[0] / 100 : 0;

        return buff.value[0] * (1 + equipBonus) + additionalValue;
    }

    /**
     * 添加天赋
     * @param player 玩家对象
     * @returns 天赋buff数组
     * 建议方法名：addTalent
     */
    // public addTianFu(player: any): any[] {
    public addTalent(player: any): any[] {
        return player.kuangrePlayer ? [Excel.shuiguobuff(player.kuangrePlayer.sgtianfuid)] : [];
    }

    /**
     * 增加玩家发送计数
     * @param player 玩家对象
     * 建议方法名：incrementPlayerSendCount
     */
    public addPlayerSendCount(player: any): void {
        const nodeId = player.node.uuid;
        this.playerSendCount[nodeId] = (this.playerSendCount[nodeId] || 0) + 1;
    }

    /**
     * 清除玩家发送计数
     * @param player 玩家对象
     * 建议方法名：clearPlayerSendCount
     */
    public clearPlayerSendCount(player: any): void {
        delete this.playerSendCount[player.node.uuid];
    }

    /**
     * 获取玩家经验值
     * @param baseExperience 初始经验值
     * @returns 最终经验值
     * 建议方法名：getPlayerExperienceValue
     */
    // public playerJingYanValue(baseExperience: number): number {
    public getPlayerExperienceValue(baseExperience: number): number {
        const experienceBonus = this.ciTiaoData.reduce((sum, ciTiao) => {
            const buff = Excel.shuiguobuff(ciTiao.citiaoshuzhitype);
            return buff.buffefftype === 47 ? sum + buff.value[0] / 100 : sum;
        }, 0);

        return baseExperience * (1 + experienceBonus);
    }

    /**
     * 获取叠加状态
     * @param player 玩家对象
     * @returns 是否叠加
     * 建议方法名：isStacked
     */
    // public getDieJia(player: any): boolean {
    public isStacked(player: any): boolean {
        return this.ciTiaoData.some(ciTiao => {
            return ciTiao.shuiguoId === player.playerId + 1000 && Excel.shuiguobuff(ciTiao.citiaoshuzhitype).buffefftype === 35;
        });
    }

    /**
     * 获取当前速度比例
     * @returns 速度比例
     * 建议方法名：getCurrentSpeedRatio
     */
    // public getNowSpeedBiLi(): number {
    public getCurrentSpeedRatio(): number {
        return this.ciTiaoData.reduce((sum, ciTiao) => {
            const buff = Excel.shuiguobuff(ciTiao.citiaoshuzhitype);
            return buff.buffefftype === 19 ? sum + buff.value[0] / 100 : sum;
        }, 0);
    }

    /**
     * 获取连续攻击
     * @param player 玩家对象
     * @returns 是否连续攻击
     * 建议方法名：isContinuousAttack
     */
    // public getLianXuAttack(player: any): boolean {
    public isContinuousAttack(player: any): boolean {
        return this.ciTiaoData.some(ciTiao => {
            return ciTiao.shuiguoId === player.playerId + 1000 && Excel.shuiguobuff(ciTiao.citiaoshuzhitype).buffefftype === 18;
        });
    }

    /**
     * 获取水果buff
     * @param fruitId 水果ID
     * @param player 玩家对象
     * @returns 水果buff值
     * 建议方法名：getFruitBuff
     */
    // public getShuiGuoBuff(fruitId: number, player: any): { nowvalue: number, otherValue: number } {
    public getFruitBuff(fruitId: number, player: any): { nowvalue: number, otherValue: number } {
        const fruit = Excel.shuiguo(fruitId);
        const buff = Excel.shuiguobuff(fruit.talent);
        let value = buff.value[0];

        if (fruitId === 1002) {
            value = this.getFruitBonus(player);
        } else if (fruitId === 1003) {
            value = this.getHamiMelonBonus(player);
        }

        const otherValue = buff.value[1] !== undefined ? buff.value[1] : -1;

        return { nowvalue: value, otherValue: otherValue };
    }

    /**
     * 获取水果加成
     * @param player 玩家对象
     * @returns 加成值
     * 建议方法名：getFruitBonus
     */
    // public getShuiGuoJiaCheng(player: any): number {
    public getFruitBonus(player: any): number {
        const fruit = Excel.shuiguo(1002);
        const equipData = ExcelUtil.getMatchingData(Excel.shuiguohecheng_all, "shuiguoId", 1002)[player];
        const baseValue = Excel.shuiguobuff(fruit.talent).value[0];
        
        let bonus = 0;
        if (equipData && equipData.addbeidongbuff[0]) {
            bonus = equipData.addbeidongbuff[0] / 100;
        }
        
        return baseValue * (1 + bonus);
    }

    /**
     * 获取哈密瓜加成
     * @param player 玩家对象
     * @returns 加成值
     * 建议方法名：getHamiMelonBonus
     */
    // public getHaMiGuaJiaCheng(player: any): number {
    public getHamiMelonBonus(player: any): number {
        const fruit = Excel.shuiguo(1003);
        const equipData = ExcelUtil.getMatchingData(Excel.shuiguohecheng_all, "shuiguoId", 1003)[player];
        const baseValue = Excel.shuiguobuff(fruit.talent).value[0];
        
        let bonus = 0;
        if (equipData && equipData.addbeidongbuff[0]) {
            bonus = equipData.addbeidongbuff[0] / 100;
        }
        
        return baseValue * (1 + bonus);
    }

    /**
     * 设置狂热buff
     * @param player 玩家对象
     * 建议方法名：setFrenzyBuff
     */
    // public setKuangReBuff(player: any): void {
    public setFrenzyBuff(player: any): void {
        const siblings = player.node.parent.children;
        const potentialTargets = siblings.filter(sibling => {
            const siblingPlayer = sibling.getComponent(ViewPlayer);
            return sibling.uuid !== player.node.uuid && !siblingPlayer.kuangrePlayer
                && ![5, 8, 9].includes(siblingPlayer.sgattacktagtype);
        });

        if (potentialTargets.length > 0) {
            const randomTarget = potentialTargets[CommonUtils.getRandomInteger(0, potentialTargets.length - 1)];
            randomTarget.setKuangRe(player);
        }
    }

    private hasBuffEffectType(effectType: number): boolean {
        return this.ciTiaoData.some(ciTiao => {
            return Excel.shuiguobuff(ciTiao.citiaoshuzhitype).buffefftype === effectType;
        });
    }

    private calculateBuffValueByEffectType(effectType: number, divider: number): number {
        return this.ciTiaoData.reduce((sum, ciTiao) => {
            const buff = Excel.shuiguobuff(ciTiao.citiaoshuzhitype);
            return buff.buffefftype === effectType ? sum + buff.value[0] / divider : sum;
        }, 0);
    }

    private countBuffEffectType(effectType: number): number {
        return this.ciTiaoData.reduce((count, ciTiao) => {
            return Excel.shuiguobuff(ciTiao.citiaoshuzhitype).buffefftype === effectType ? count + 1 : count;
        }, 0);
    }
}

export const BuffMgr = BuffManager.getInstance();

